#include "pwm_out.h"
#include "math.h"
#include "parameters.h"

static TIM_OCInitTypeDef TIM_OCInitStructure;
static uint16_t          TimerPeriod = 0;

void PWM_Init(void) {
    GPIO_InitTypeDef        GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    DAC1_TIM_CLK_INIT(DAC1_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(DAC1_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = DAC1_GPIO_PIN;
    GPIO_Init(DAC1_GPIO_PORT, &GPIO_InitStructure);

    DAC2_TIM_CLK_INIT(DAC2_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(DAC2_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = DAC2_GPIO_PIN;
    GPIO_Init(DAC2_GPIO_PORT, &GPIO_InitStructure);

    DAC3_TIM_CLK_INIT(DAC3_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(DAC3_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = DAC3_GPIO_PIN;
    GPIO_Init(DAC3_GPIO_PORT, &GPIO_InitStructure);

    DAC4_TIM_CLK_INIT(DAC4_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(DAC4_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = DAC4_GPIO_PIN;
    GPIO_Init(DAC4_GPIO_PORT, &GPIO_InitStructure);

    DAC5_TIM_CLK_INIT(DAC5_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(DAC5_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = DAC5_GPIO_PIN;
    GPIO_Init(DAC5_GPIO_PORT, &GPIO_InitStructure);

    DAC6_TIM_CLK_INIT(DAC6_TIM_CLK, ENABLE);
    RCC_APB2PeriphClockCmd(DAC6_GPIO_CLK, ENABLE);
    GPIO_InitStructure.GPIO_Pin = DAC6_GPIO_PIN;
    GPIO_Init(DAC6_GPIO_PORT, &GPIO_InitStructure);

    /* Compute the value to be set in ARR regiter to generate signal frequency at 17.57 Khz */
    // TimerPeriod = (SystemCoreClock / 17570 ) - 1;
    TimerPeriod = (SystemCoreClock / (72 - 1) / OUT_FREQ);   // 1000hz

    /* Time Base configuration */
    TIM_TimeBaseStructure.TIM_Prescaler         = (72 - 1);
    TIM_TimeBaseStructure.TIM_CounterMode       = TIM_CounterMode_Up;
    TIM_TimeBaseStructure.TIM_Period            = TimerPeriod - 1;
    TIM_TimeBaseStructure.TIM_ClockDivision     = 0;
    TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

    TIM_TimeBaseInit(DAC6_TIM, &TIM_TimeBaseStructure);

    /* PWM1 Mode configuration: Channel4 */
    TIM_OCInitStructure.TIM_OCMode      = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_Pulse       = 0;
    TIM_OCInitStructure.TIM_OCPolarity  = TIM_OCPolarity_High;

    TIM_TimeBaseInit(DAC1_TIM, &TIM_TimeBaseStructure);
    TIM_OCInitStructure.TIM_Pulse = 0;
    DAC1_TIM_OCInit(DAC1_TIM, &TIM_OCInitStructure);
    DAC1_TIM_OCPreloadConfig(DAC1_TIM, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(DAC1_TIM, ENABLE);
    TIM_CtrlPWMOutputs(DAC1_TIM, ENABLE);   // 定时器1 和定时器8  输出PWM 时 需要添加这条
    TIM_Cmd(DAC1_TIM, ENABLE);

    TIM_TimeBaseInit(DAC2_TIM, &TIM_TimeBaseStructure);
    TIM_OCInitStructure.TIM_Pulse = 0;
    DAC2_TIM_OCInit(DAC2_TIM, &TIM_OCInitStructure);
    DAC2_TIM_OCPreloadConfig(DAC2_TIM, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(DAC2_TIM, ENABLE);
    // TIM_CtrlPWMOutputs(DAC2_TIM, ENABLE); //定时器1 和定时器8  输出PWM 时 需要添加这条
    TIM_Cmd(DAC2_TIM, ENABLE);

    TIM_TimeBaseInit(DAC3_TIM, &TIM_TimeBaseStructure);
    TIM_OCInitStructure.TIM_Pulse = 0;
    DAC3_TIM_OCInit(DAC3_TIM, &TIM_OCInitStructure);
    DAC3_TIM_OCPreloadConfig(DAC3_TIM, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(DAC3_TIM, ENABLE);
    // TIM_CtrlPWMOutputs(DAC2_TIM, ENABLE); //定时器1 和定时器8  输出PWM 时 需要添加这条
    TIM_Cmd(DAC3_TIM, ENABLE);

    TIM_TimeBaseInit(DAC4_TIM, &TIM_TimeBaseStructure);
    TIM_OCInitStructure.TIM_Pulse = 0;
    DAC4_TIM_OCInit(DAC4_TIM, &TIM_OCInitStructure);
    DAC4_TIM_OCPreloadConfig(DAC4_TIM, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(DAC4_TIM, ENABLE);
    // TIM_CtrlPWMOutputs(DAC2_TIM, ENABLE); //定时器1 和定时器8  输出PWM 时 需要添加这条
    TIM_Cmd(DAC4_TIM, ENABLE);

    TIM_TimeBaseInit(DAC5_TIM, &TIM_TimeBaseStructure);
    TIM_OCInitStructure.TIM_Pulse = 0;
    DAC5_TIM_OCInit(DAC5_TIM, &TIM_OCInitStructure);
    DAC5_TIM_OCPreloadConfig(DAC5_TIM, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(DAC5_TIM, ENABLE);
    // TIM_CtrlPWMOutputs(DAC5_TIM, ENABLE); //定时器1 和定时器8  输出PWM 时 需要添加这条
    TIM_Cmd(DAC5_TIM, ENABLE);

    DAC6_TIM_OCInit(DAC6_TIM, &TIM_OCInitStructure);
    DAC6_TIM_OCPreloadConfig(DAC6_TIM, TIM_OCPreload_Enable);
    TIM_ARRPreloadConfig(DAC6_TIM, ENABLE);
    TIM_CtrlPWMOutputs(DAC6_TIM, ENABLE);   // 定时器1 和定时器8  输出PWM 时 需要添加这条
    TIM_Cmd(DAC6_TIM, ENABLE);
}

void PWM1_Set(u16 percent_10) {
    uint16_t Pulse = 0;
    Pulse          = (uint16_t) (((uint32_t) percent_10 * (TimerPeriod)) / 1000);
    TIM_SetCompare1(DAC1_TIM, Pulse);
}
void PWM2_Set(u16 percent_10) {
    uint16_t Pulse = 0;
    Pulse          = (uint16_t) (((uint32_t) percent_10 * (TimerPeriod)) / 1000);
    TIM_SetCompare2(DAC2_TIM, Pulse);
}
void PWM3_Set(u16 percent_10) {
    uint16_t Pulse = 0;
    Pulse          = (uint16_t) (((uint32_t) percent_10 * (TimerPeriod)) / 1000);
    TIM_SetCompare3(DAC3_TIM, Pulse);
}
void PWM4_Set(u16 percent_10) {
    uint16_t Pulse = 0;
    Pulse          = (uint16_t) (((uint32_t) percent_10 * (TimerPeriod)) / 1000);
    TIM_SetCompare4(DAC4_TIM, Pulse);
}
void PWM5_Set(u16 percent_10) {
    uint16_t Pulse = 0;
    Pulse          = (uint16_t) (((uint32_t) percent_10 * (TimerPeriod)) / 1000);
    TIM_SetCompare3(DAC5_TIM, Pulse);
}
void PWM6_Set(u16 percent_10) {
    uint16_t Pulse = 0;
    Pulse          = (uint16_t) (((uint32_t) percent_10 * (TimerPeriod)) / 1000);
    TIM_SetCompare4(DAC6_TIM, Pulse);
}

// 实测电压{0, 89, 176, 266, 360, 456, 557, 662, 771, 884, 1000};
static u16 pwm_adjust[11] = {0, 112, 227, 338, 444, 547, 646, 740, 830, 919, 1000};

static u16 pwm_swtich(u8 degree) {
    if (degree >= 100) {
        return 1000;
    }

    u16 i = degree / 10;
    u16 j = degree % 10;

    float base  = pwm_adjust[i];
    float delta = pwm_adjust[i + 1] - pwm_adjust[i];
    float per   = delta / 10.0f * j;

    float result = base + per;
    return (u16) roundf(result);
}
// 设置占空比函数（duty: 0~100）
void PWM_SetDuty(u16 channel, u8 duty) {
    if (duty > 100) {
        duty = 100;
    }
    u16 pwm_value = 0;
    u32 pulse     = 0;
    pwm_value     = pwm_swtich(duty);
    pulse         = (uint16_t) (((uint32_t) pwm_value * (TimerPeriod)) / 1000);

    switch (channel) {
        case PWM_CHANNEL_1:
            TIM_SetCompare1(DAC1_TIM, pulse);
            break;
        case PWM_CHANNEL_2:
            TIM_SetCompare2(DAC2_TIM, pulse);
            break;
        case PWM_CHANNEL_3:
            TIM_SetCompare3(DAC3_TIM, pulse);
            break;
        case PWM_CHANNEL_4:
            TIM_SetCompare4(DAC4_TIM, pulse);
            break;
        case PWM_CHANNEL_5:
            TIM_SetCompare3(DAC5_TIM, pulse);
            break;
        case PWM_CHANNEL_6:
            TIM_SetCompare4(DAC6_TIM, pulse);
            break;

        default:
            break;
    }
}
